import { newGuid } from '@/utils';

export default function(G6) {
    G6.registerBehavior('dragEdge', {
        getDefaultCfg() {
            // 与 model 合并
            return {
                updateEdge: true,
                // 是否委托，常量不修改
                delegate: true,
                delegateStyle: {},
                dragEdge: false,
            };
        },
        getEvents() {
            return {
                'anchor:dragstart': 'onDragStart',
                'anchor:drag': 'onDrag',
                'anchor:dragend': 'onDragEnd',
                'anchor:dragenter': 'onDragEnter',
                'anchor:dragleave': 'onDragLeave',
            };
        },
        onDragEnter(e) {
            console.log(e, '锚点eeeee进来了');
            // 拖拽元素进入目标元素时触发
            if (!this.origin) {
                return;
            }
            if (!this.sameNode(e)) {
                e.item.setHotspotActived(true);
                this.origin.targetNode = e.target
                    .getParent()
                    .getParent()
                    .get('item');
                this.origin.targetAnchor = e.item.get('index');
            }
        },
        onDragLeave(e) {
            if (!this.origin) {
                return;
            }
            if (!this.sameNode(e)) {
                e.item.setHotspotActived(false);
                this.origin.targetNode = null;
                this.origin.targetAnchor = null;
            }
        },
        onDragStart(e) {
            const node = e.target
                .getParent()
                .getParent()
                .get('item');

            const anchorIndex = e.item.get('index'); // 上0  下1
            const point = node.getAnchorPoints()[anchorIndex];

            this.target = e.item;
            let id = newGuid();
            this.origin = {
                id: id,
                x: point.x,
                y: point.y,
                sourceNode: node,
                sourceAnchor: anchorIndex,
            };
            this.dragEdgeBeforeShowAnchor(e);
            this.graph.set('onDragEdge', true);
        },
        onDrag(e) {
            if (!this.origin) {
                return;
            }
            this._updateEdge(this.target, e);
        },
        onDragEnd(e) {
            if (!this.origin) {
                return;
            }
            const delegateShape = e.item.get('edgeDelegate');

            if (delegateShape) {
                delegateShape.remove();
                this.target.set('edgeDelegate', null);
            }

            this._updateEdge(this.target, e, true);
            this.graph.setItemState(this.origin.sourceNode, 'show-anchor', false);
            this.target = null;
            this.origin = null;
            this.graph.set('onDragEdge', false);
        },
        sameNode(e) {
            return (
                e.target.type === 'marker' &&
                e.target.getParent() &&
                e.target
                    .getParent()
                    .getParent()
                    .get('item')
                    .get('id') === this.origin.sourceNode.get('id')
            );
        },

        /**
         * 连线之前，显示所有的锚点，已经连接了的不能再次连接
         * 怎么定义上进下出呢？
         * */
        dragEdgeBeforeShowAnchor() {
            let edges = this.graph.getEdges();

            // 找到已经连接了的线，return 出 sourceNode
            let sameEdges = edges.filter((edge) => {
                if (edge.get('sourceNode').get('id') == this.origin.sourceNode.get('id')) {
                    return edge.get('sourceNode');
                }
            });
            // 已经连接了的节点的 id，不允许再次连接（改成，已经连接的锚点，不允许再次连接）
            let connectNode = sameEdges.map((edge) => {
                const node = edge.get('targetNode');
                return {
                    nodeId: node.get('id'),
                    anchorIndex: edge.get('targetAnchorIndex'),
                };
            });
            this.graph.getNodes().forEach((node) => {
                //已经连接的锚点排除
                let excludeAnchorIndexs = [];
                const cNode = connectNode.find((cn) => cn.nodeId === node.get('id'));
                if (cNode) {
                    excludeAnchorIndexs.push(cNode.anchorIndex);
                }

                //外部验证锚点连接规则
                if (this.graph.linkAnchorRule && typeof this.graph.linkAnchorRule === 'function') {
                    const customExcludeAnchorIndexs = this.graph.linkAnchorRule(this.origin.sourceNode, this.origin.sourceAnchor, node);
                    if (Array.isArray(customExcludeAnchorIndexs)) {
                        excludeAnchorIndexs = excludeAnchorIndexs.concat(customExcludeAnchorIndexs);
                        excludeAnchorIndexs = Array.from(new Set(excludeAnchorIndexs));
                    } else {
                        if (!customExcludeAnchorIndexs) {
                            return;
                        }
                    }
                }

                const group = node.getContainer();
                if (group) {
                    group.showAnchor(group, excludeAnchorIndexs);
                    group.anchorShapes.forEach((a) => a.get('item').showHotpot());
                }
            });
            // let connectedNodeIds = sameEdges.map(i => i.get('targetNode').get('id'));
            // this.graph.getNodes().forEach(node => {
            //     if (!connectedNodeIds.includes(node.get('id'))) {
            //         const group = node.getContainer();
            //         if (group) {
            //             group.showAnchor(group);
            //             group.anchorShapes.forEach(a => a.get('item').showHotpot());
            //         }
            //     }
            // });
        },
        _updateEdge(item, e, force) {
            const x = e.x;
            const y = e.y;

            // 这里委托了虚线来表示拖拽的线
            if (this.delegate && !force) {
                this._updateEdgeDelegate(item, x, y);
                return;
            }
            this._addEdge(e);
            this._clearAllAnchor();
            this.graph.paint();
        },
        _updateEdgeDelegate(item, x, y) {
            const self = this;
            let edgeShape = item.get('edgeDelegate');
            if (!edgeShape) {
                const parent = self.graph.get('group');
                edgeShape = parent.addShape('line', {
                    attrs: {
                        x1: this.origin.x,
                        y1: this.origin.y,
                        x2: x,
                        y2: y,
                        stroke: '#1890FF',
                        lineDash: [4, 4],
                        lineWidth: 1,
                    },
                });
                edgeShape.set('capture', false);
                item.set('edgeDelegate', edgeShape);
            }
            edgeShape.attr({ x2: x, y2: y });
            this.graph.paint();
        },
        _clearAllAnchor() {
            this.graph.getNodes().forEach((node) => {
                const group = node.getContainer();
                group.clearAnchor(group);
            });
        },
        _addEdge() {
            if (this.origin.targetNode) {
                const addModel = {
                    id: this.origin.id,
                    //shape: 'flow-polyline-round',
                    shape: 'flow-cubic-round',
                    source: this.origin.sourceNode.get('id'),
                    target: this.origin.targetNode.get('id'),
                    sourceAnchor: this.origin.sourceAnchor,
                    targetAnchor: this.origin.targetAnchor,
                };
                if (this.graph.executeCommand) {
                    this.graph.executeCommand('add', {
                        type: 'edge',
                        addModel: addModel,
                    });
                } else {
                    this.graph.add('edge', addModel);
                }
            }
        },
    });
}
